﻿/*
 *
 * 版权：C.c 版权所有
 *
 * 作者：C.c
 *
 * 版本：1.0
 *
 * 创建日期：2017/11/02
 *
 * 描述：UI管理
 *
 * 修订历史：
 *
 */

using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;


namespace XHFrame
{

    public class UIManager : Singleton<UIManager>
    {
        /// <summary>
        /// 保存需要打开UI界面参数的数据类
        /// </summary>
        class UIInfoData
        {
            public EnumUIType UIType { get; private set; }
            public string Path { get; private set; }
            public object[] UIParams { get; private set; }
            public Type UIScriptType { get; private set; }
            /// <summary>
            /// 保存需要打开UI界面参数的数据
            /// </summary>
            /// <param name="UItype">UI类型</param>
            /// <param name="path">ui路径</param>
            /// <param name="UIParams">ui</param>
            public UIInfoData(EnumUIType UItype, string path, params object[] UIParams)
            {
                this.UIType = UItype;
                this.Path = path;
                this.UIScriptType = UIpathDefines.GetUIScriptByType(UIType);
                this.UIParams = UIParams;
            }
        }

        /// <summary>
        /// 保存当前已经打开的集合;
        /// </summary>
        Dictionary<EnumUIType, GameObject> dicOpenUI = null;

        /// <summary>
        /// 需要打开的UI
        /// </summary>
        Stack<UIInfoData> stackOpenUIs = null;


        /// <summary>
        /// 初始化
        /// </summary>
        public override void Init()
        {
            base.Init();
            dicOpenUI = new Dictionary<EnumUIType, GameObject>();
            stackOpenUIs = new Stack<UIInfoData>();
        }

        /// <summary>
        /// 获得指定类型的UI对象
        /// </summary>
        /// <typeparam name="T"> UI类型 </typeparam>
        /// <param name="_uiType"> UI对象 </param>
        /// <returns></returns>
        public T GetUI<T>(EnumUIType _uiType) where T : BaseUI
        {
            GameObject _retObj = GetUIObject(_uiType);
            if (_retObj != null)
            {
                return _retObj.GetComponent<T>();
            }
            return null;

        }

        /// <summary>
        /// 返回UI对象
        /// </summary>
        /// <param name="_uiType"></param>
        /// <returns></returns>
        public GameObject GetUIObject(EnumUIType _uiType)
        {
            GameObject _retObj = null;
            if (!dicOpenUI.TryGetValue(_uiType, out _retObj))
                throw new Exception("_dicOpenUIs TryGeyValue failure! _uiType" + _uiType.ToString());
            return _retObj;
        }

        /// <summary>
        /// 预加载单个UI
        /// </summary>
        /// <param name="_uiType">需要预加载的UI</param>
        public void PreloadUI(EnumUIType _uiType)
        {
            string _path = UIpathDefines.GetUIPrefabsPathByType(_uiType);
            Resources.Load(_path);
        }
        /// <summary>
        /// 预加载多个UI
        /// </summary>
        /// <param name="_uiType">需要预加载的多个UI</param>
        public void PreloadUI(EnumUIType[] _UIType)
        {
            for (int i = 0; i < _UIType.Length; i++)
            {
                PreloadUI(_UIType[i]);
            }
        }


        /// <summary>
        /// 打开UI
        /// </summary>
        /// <param name="UIType">需要打开的UI</param>
        /// <param name="_uiParams"></param>
        public void OpenUI(EnumUIType UIType, params object[] _uiParams)
        {
            EnumUIType[] uIType = new EnumUIType[1] { UIType };
            OpenUI(false, uIType, _uiParams);
        }

        /// <summary>
        /// 打开UI
        /// </summary>
        /// <param name="UIType">需要打开的UI</param>
        public void OpenUI(EnumUIType[] UIType)
        {
            OpenUI(false, UIType, null);
        }
        /// <summary>
        /// 打开UI移除其他
        /// </summary>
        /// <param name="UIType">需要打开的UI</param>
        public void OpenUICloesOthers(EnumUIType[] UIType)
        {
            OpenUI(true, UIType, null);
        }
        /// <summary>
        /// 打开UI移除其他
        /// </summary>
        /// <param name="UIType">需要打开的UI</param>
        /// <param name="_uiParams"></param>
        public void OpenUICloesOthers(EnumUIType UIType, params object[] UIParams)
        {
            EnumUIType[] uIType = new EnumUIType[1] { UIType };
            OpenUI(true, uIType, UIParams);
        }


        /// <summary>
        /// 打开UI
        /// </summary>
        /// <param name="_IsCloseOthers">是否关闭其他UI</param>
        /// <param name="_uiTypes">需要打开的UI</param>
        /// <param name="_uiParams"></param>
        public void OpenUI(bool _IsCloseOthers, EnumUIType[] _uiTypes, params object[] _uiParams)
        {
            if (_IsCloseOthers)
            {
                // Close Others ui
                CloseUIAll();
            }
            for (int i = 0; i < _uiTypes.Length; i++) // 打开UITypes
            {
                EnumUIType uIType = _uiTypes[i];
                if (!dicOpenUI.ContainsKey(uIType)) // 将uiType添加到栈集合中;
                {
                    string _path = UIpathDefines.GetUIPrefabsPathByType(uIType);
                    stackOpenUIs.Push(new UIInfoData(uIType, _path, _uiParams));
                }
            }
            if (stackOpenUIs.Count > 0)// Open ui 协同加载UI
            {
                CoroutineController.Instance.StartCoroutine(AsyncLoadData());
            }
        }


        /// <summary>
        /// 打开UI逻辑
        /// </summary>
        /// <returns></returns>
        private IEnumerator<int> AsyncLoadData()
        {
            UIInfoData uIInfoData = null;
            UnityEngine.Object _prefabObj = null;
            GameObject _UIobj = null;

            if (stackOpenUIs != null && stackOpenUIs.Count > 0)
            {
                do
                {
                    uIInfoData = stackOpenUIs.Pop();
                    _prefabObj = Resources.Load(uIInfoData.Path);
                    if (_prefabObj != null)
                    {
                        _UIobj = MonoBehaviour.Instantiate(_prefabObj) as GameObject;
                        BaseUI baseUI = _UIobj.GetComponent<BaseUI>();
                        if (null == baseUI)
                        {
                            baseUI = _UIobj.AddComponent(uIInfoData.UIScriptType) as BaseUI;
                        }
                        if (null != baseUI)
                        {
                            baseUI.SetUIWhenOpening(uIInfoData.UIParams);
                        }
                        dicOpenUI.Add(uIInfoData.UIType, _UIobj);
                    }
                } while (stackOpenUIs.Count > 0);

            }
            yield return 0;
        }

        /// <summary>
        /// 关闭所有UI
        /// </summary>
        public void CloseUIAll()
        {
            List<EnumUIType> listKey = new List<EnumUIType>(dicOpenUI.Keys);
            for (int i = 0; i < listKey.Count; i++)
            {
                CloseUI(listKey[i]);
            }
            dicOpenUI.Clear();
        }

        /// <summary>
        /// 关闭多个UI
        /// </summary>
        /// <param name="uIType">需要关闭的UI类型</param>
        public void CloseUI(EnumUIType[] uIType)
        {
            for (int i = 0; i < uIType.Length; i++)
            {
                CloseUI(uIType[i]);
            }
        }


        /// <summary>
        /// 关闭UI
        /// </summary>
        /// <param name="uIType"> 需要关闭的UI类型 </param>
        public void CloseUI(EnumUIType uIType)
        {
            GameObject _UIObj = GetUIObject(uIType);
            if (null == _UIObj)
            {
                dicOpenUI.Remove(uIType);
            }
            else
            {
                BaseUI _baseUI = _UIObj.GetComponent<BaseUI>();
                if (null == _baseUI)
                {
                    GameObject.Destroy(_UIObj);
                    dicOpenUI.Remove(uIType);
                }
                else
                {
                    _baseUI.OnStateChanged += CloseUIHandle;
                    _baseUI.OnRelease();
                }
            }
        }

        /// <summary>
        /// 关闭UI处理
        /// </summary>
        /// <param name="ui"> 当前对象类 </param>
        /// <param name="newState"> 新的状态 </param>
        /// <param name="oldState"> 改变前的状态 </param>
        private void CloseUIHandle(object ui, EnumObjectState newState, EnumObjectState oldState)
        {
            if (newState == EnumObjectState.Closing)
            {
                BaseUI _baseUI = ui as BaseUI;
                dicOpenUI.Remove(_baseUI.GetUIType());
                _baseUI.OnStateChanged -= CloseUIHandle;
            }
        }
    }
}